package cn.smbms.util;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Base64;
import java.util.HashMap;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * Quick Response Code
 * @author 
 *
 */
public class QrCodeUtil {

	    /**
	     * 
	     * @param content 二维码封装内容
	     * @param weight 宽度
	     * @param height 高度
	     * @return
	     */
	    public static BufferedImage createImage(String content, Integer weight, Integer height) {
	        /**
	         * 1、如果高度和宽度都有指定，使用指定的高宽
	         * 2、如果高宽都未指定，使用默认的高宽300x300
	         * 3、只指定了高宽中的一个，则高宽相等
	         */
	        if(weight != null && height != null) {

	        }else if(weight == null && height == null) {
	            weight = 300;
	            height = 300;
	        }else {
	            weight = (weight == null ? height : weight);
	            height = (height == null ? weight : height);
	        }
	        // 相关设置
	        HashMap<EncodeHintType, Comparable<?>> hints = new HashMap<>();
	        // L(7%) M(15%) Q(25%) H(30%)
	        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
	        // 二维码边界空白大小1,2,3,4，默认4，最大
	        hints.put(EncodeHintType.MARGIN, 1);
	        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
	        try {
	            QRCodeWriter writer = new QRCodeWriter();
	            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, weight, height, hints);
	            BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
	            return image;
	        } catch (WriterException e) {
	        	e.printStackTrace();
	        }
	        return null;
	    }

	    /**
	     * 	输出二维码到流中，在本项目中输出到流中会出现换行，导致输出乱码，原因不详，建议使用base64输出形式
	     * @param content
	     * @param logo
	     * @param stream
	     * @param weight
	     * @param height
	     */
	    public static void writeToStream(String content, OutputStream stream, Integer weight, Integer height) {
	        try {
	            BufferedImage image = createImage(content, weight, height);
	            // 输出图片为png格式
	            ImageIO.write(image, "png", stream);
	        } catch (IOException e) {
	        	e.printStackTrace();
	        }
	    }

	    /**
	     *    以base64形式输出二维码
	     * @param content
	     * @param logo
	     * @param weight
	     * @param height
	     * @return
	     */
	    public static String writeToBase64(String content, Integer weight, Integer height){
	        try {
	            BufferedImage image = createImage(content, weight, height);
	            ByteArrayOutputStream bos = new ByteArrayOutputStream();
	            // 输出图片为png格式
	            ImageIO.write(image, "png", bos);
	            return "data:image/png;base64," + Base64.getEncoder().encode(bos.toByteArray());
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	        return "";
	    }
    
	    public static String decodeQr(String filePath) {
	        String retStr = "";
	        if (filePath==null || "".equals(filePath)) {
	            return "图片路径为空";
	        }
	        try {
	            BufferedImage bufferedImage = ImageIO.read(new FileInputStream(filePath));
	            LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
	            Binarizer binarizer = new HybridBinarizer(source);
	            BinaryBitmap bitmap = new BinaryBitmap(binarizer);
	            HashMap<DecodeHintType, Object> hintTypeObjectHashMap = new HashMap<>();
	            hintTypeObjectHashMap.put(DecodeHintType.CHARACTER_SET, "UTF-8");
	            Result result = new MultiFormatReader().decode(bitmap, hintTypeObjectHashMap);
	            retStr = result.getText();
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	        return retStr;
	    }	    
	    
	    public static void main(String[] args) throws Exception {
		    QrCodeUtil.writeToStream("test", new FileOutputStream("d:/temp/qr.png"), 300, 300);
		    System.out.println(QrCodeUtil.decodeQr("d:/temp/qr.png"));
	    }
}
